#light

namespace CGraph.SchemaGraph.Impl

open CGraph.SchemaGraph
open CGraph.DirectedGraph
open CGraph.DirectedGraph.Impl
        
        
type DatatypeVertex(graph:ISchemaGraph,m_name:string) =
    inherit Vertex(graph :?> IDirectedGraph) as base
    interface IDatatypeVertex with
        member this.Name with get() = m_name
        
type SimpleDatatypeVertex(graph:ISchemaGraph,m_name:string) =
    inherit DatatypeVertex(graph,m_name) as base
    interface ISimpleDatatypeVertex
        
type ComplexDatatypeVertex(graph:ISchemaGraph,m_name:string) =
    inherit DatatypeVertex(graph,m_name) as base
    interface IComplexDatatypeVertex
    
type DocumentationVertex(graph:ISchemaGraph,m_documentation:string) =
    inherit Vertex(graph :?> IDirectedGraph) as base
    interface IDocumentationVertex with
        member this.Documentation with get() = m_documentation
        
type LocalAttributeVertex(m_graph:ISchemaGraph,m_name:string,m_default:string option,m_fixed:string option) =
    inherit Vertex(m_graph :?> IDirectedGraph) as base
    interface ILocalAttributeVertex with
        member this.Name with get() = m_name
        member this.Default with get() = m_default
        member this.Fixed with get() = m_fixed
        
type ComplexSimpleExtension(m_graph:ISchemaGraph) =
    inherit Vertex(m_graph :?> IDirectedGraph) as base
    interface IComplexSimpleExtension
    
type ComplexSimpleRestriction(m_graph:ISchemaGraph) =
    inherit Vertex(m_graph :?> IDirectedGraph) as base
    interface IComplexSimpleRestriction
    
type ComplexComplexExtension(m_graph:ISchemaGraph) =
    inherit Vertex(m_graph :?> IDirectedGraph) as base
    interface IComplexComplexExtension
    
type ComplexComplexRestriction(m_graph:ISchemaGraph) =
    inherit Vertex(m_graph :?> IDirectedGraph) as base
    interface IComplexComplexRestriction
    
type SequenceVertex(m_graph:ISchemaGraph, m_min:MinMaxValue, m_max:MinMaxValue ) =
    inherit Vertex( m_graph :?> IDirectedGraph )
    interface ISequenceVertex with
        member this.Min with get() = m_min
        member this.Max with get() = m_max
        
type ChoiceVertex(m_graph:ISchemaGraph, m_min:MinMaxValue, m_max:MinMaxValue ) =
    inherit Vertex( m_graph :?> IDirectedGraph )
    interface IChoiceVertex with
        member this.Min with get() = m_min
        member this.Max with get() = m_max
        
type ParticleElementVertex(m_graph:ISchemaGraph, m_min:MinMaxValue, m_max:MinMaxValue ) =
    inherit Vertex( m_graph :?> IDirectedGraph )
    interface IParticleElement with
        member this.Min with get() = m_min
        member this.Max with get() = m_max
        
type AnyVertex(m_graph:ISchemaGraph, m_min:MinMaxValue, m_max:MinMaxValue) =
    inherit Vertex( m_graph :?> IDirectedGraph )
    interface IAnyVertex with
        member this.Min with get() = m_min
        member this.Max with get() = m_max
        
type GroupRefVertex(m_graph:ISchemaGraph, m_min:MinMaxValue, m_max:MinMaxValue) =
    inherit Vertex( m_graph :?> IDirectedGraph )
    interface IGroupRef with
        member this.Min with get() = m_min
        member this.Max with get() = m_max
  
type SchemaEdgeBase(graph:ISchemaGraph, incoming:IDatatypeVertex, outgoing:IDatatypeVertex)=
    inherit Edge((graph :?> IDirectedGraph),(incoming :?> IVertex),(outgoing :?> IVertex)) as base
        
type ExtensionEdge(graph:ISchemaGraph, incoming:IDatatypeVertex, outgoing:IVertex) =
    inherit Edge((graph :?> IDirectedGraph),(incoming :?> IVertex),outgoing) as base
    interface IExtensionEdge
    
type ListDerivationEdge(graph:ISchemaGraph, incoming:ISimpleDatatypeVertex, outgoing:ISimpleDatatypeVertex) =
    inherit SchemaEdgeBase(graph,(incoming :?> IDatatypeVertex),(outgoing :?> IDatatypeVertex)) as base
    interface IListDerivationEdge
    
type RestrictionEdge(graph:ISchemaGraph, incoming:IDatatypeVertex, outgoing:IDatatypeVertex) =
    inherit SchemaEdgeBase(graph,incoming,outgoing) as base
    interface IRestrictionEdge
    
type DocumentationEdge(graph:ISchemaGraph, incoming:IVertex, outgoing:IDocumentationVertex) =
    inherit Edge((graph :?>IDirectedGraph), incoming, (outgoing :?>IVertex))
    interface IDocumentationEdge

type LocalAttributeEdge(graph:ISchemaGraph,incoming:IVertex,outgoing:ILocalAttributeVertex) =
    inherit Edge((graph :?>IDirectedGraph), incoming, (outgoing :?>IVertex))
    interface ILocalAttributeEdge

type DatatypeReferenceEdge(graph:ISchemaGraph,incoming:IVertex,outgoing:IDatatypeVertex) =
    inherit Edge((graph :?>IDirectedGraph), incoming, (outgoing :?>IVertex))
    interface IDatatypeReferenceEdge 
    
type NamedDatatypeReferenceEdge(graph:ISchemaGraph,incoming:IVertex,outgoing:IDatatypeVertex,m_name:string) =
    inherit Edge((graph :?>IDirectedGraph), incoming, (outgoing :?>IVertex))
    interface INamedDatatypeReferenceEdge with
        member this.Name with get() = m_name
    
type ComplexContentEdge(graph:ISchemaGraph,incoming:IComplexDatatypeVertex,outgoing:IComplexContent)=
    inherit Edge((graph :?>IDirectedGraph), (incoming :?> IVertex), (outgoing :?>IVertex))
    interface IComplexContentEdge
    
type ParticleEdge(graph:ISchemaGraph,incoming:IVertex,outgoing:IParticle) =
    inherit Edge((graph:?>IDirectedGraph), incoming, (outgoing :?> IVertex))
    interface IParticleEdge
    
type SchemaGraphEdgeCollection(graph:ISchemaGraph, vertex_access:unit->seq<IVertex>) =
    inherit EdgeCollection( (graph :?> IDirectedGraph), vertex_access ) as base
    interface ISchemaEdgeCollection with
        member this.Restrict inc out = 
            let retval = new RestrictionEdge( graph, inc, out )
            retval.Add()
            retval :> IRestrictionEdge
            
        member this.Extend inc out = 
            let retval = new ExtensionEdge( graph, inc, out )
            retval.Add()
            retval  :> IExtensionEdge
            
        member this.DeriveList inc out =
            let retval = new ListDerivationEdge( graph, inc, out )
            retval.Add()
            retval :> IListDerivationEdge
            
        member this.Document vert documentation =
            let docVertex = graph.Vertexes.CreateDocumentationVertex documentation
            let retval = new DocumentationEdge( graph, vert, docVertex )
            retval.Add()
            retval :> IDocumentationEdge
        
        member this.AddLocalAttribute vert attVert =
            let retval = new LocalAttributeEdge( graph, vert, attVert )
            retval.Add()
            retval :> ILocalAttributeEdge
            
        member this.Reference vert dtypeVert = 
            let retval = new DatatypeReferenceEdge( graph, vert, dtypeVert )
            retval.Add()
            retval :> IDatatypeReferenceEdge
            
        member this.NamedReference name vert dtypeVert = 
            let retval = new NamedDatatypeReferenceEdge( graph, vert, dtypeVert, name )
            retval.Add()
            retval :> INamedDatatypeReferenceEdge
         
        member this.ComplexContent complex content =
            let retval = new ComplexContentEdge( graph, complex, content )
            retval.Add()
            retval :> IComplexContentEdge
            
        member this.Particle vert part =
            let retval = new ParticleEdge( graph, vert, part )
            retval.Add()
            retval :> IParticleEdge
        
type SchemaGraphVertexCollection(graph:ISchemaGraph) =
    inherit VertexCollection(graph :?> IDirectedGraph) as base
    abstract AddVertex : IVertex -> unit
    default this.AddVertex vert = base.InternalVertexes.Add( vert )
    
    interface ISchemaVertexCollection with
        member this.CreateSimpleVertex name = 
            let newVert = new SimpleDatatypeVertex( graph, name )
            this.AddVertex( newVert )
            newVert :> ISimpleDatatypeVertex
            
        member this.CreateComplexVertex name =
            let newVert = new ComplexDatatypeVertex( graph, name )
            this.AddVertex( newVert )
            newVert :> IComplexDatatypeVertex
            
        member this.CreateDocumentationVertex name =
            let newVert = new DocumentationVertex( graph, name )
            this.AddVertex( newVert )
            newVert :> IDocumentationVertex
            
        member this.CreateLocalAttributeVertex name (def:string option) (ffed:string option) = 
            let newVert = new LocalAttributeVertex( graph, name, def, ffed )
            this.AddVertex newVert
            newVert :> ILocalAttributeVertex
            
        member this.CreateComplexSimpleExtension() = 
            let newVert = new ComplexSimpleExtension( graph )
            this.AddVertex newVert
            newVert :> IComplexSimpleExtension
            
        member this.CreateComplexSimpleRestriction() = 
            let newVert = new ComplexSimpleRestriction( graph )
            this.AddVertex newVert
            newVert :> IComplexSimpleRestriction
            
        member this.CreateComplexComplexExtension() = 
            let newVert = new ComplexComplexExtension( graph )
            this.AddVertex newVert
            newVert :> IComplexComplexExtension
            
        member this.CreateComplexComplexRestriction() = 
            let newVert = new ComplexComplexRestriction( graph )
            this.AddVertex newVert
            newVert :> IComplexComplexRestriction
            
        member this.CreateSequence min max =
            let newVert = new SequenceVertex( graph, min, max )
            this.AddVertex newVert
            newVert :> ISequenceVertex
            
        member this.CreateChoice min max =
            let newVert = new ChoiceVertex( graph, min, max )
            this.AddVertex newVert
            newVert :> IChoiceVertex
            
        member this.CreateAny min max =
            let newVert = new AnyVertex( graph, min, max)
            this.AddVertex newVert
            newVert :> IAnyVertex
            
        member this.CreateParticleElement min max =
            let newVert = new ParticleElementVertex( graph, min, max )
            this.AddVertex newVert
            newVert :> IParticleElement
           
        member this.CreateGroupRef min max =
            let newVert = new GroupRefVertex( graph, min, max )
            this.AddVertex newVert
            newVert :> IGroupRef
            
            
type SchemaGraph =
    inherit DirectedGraph as base
    new() as this = 
        {}
        then
            let vc = new SchemaGraphVertexCollection (this :> ISchemaGraph)
            let ec = new SchemaGraphEdgeCollection( (this :> ISchemaGraph), (fun() -> this.m_vertexes :> seq<IVertex>) )
            this.m_vertexes <- (vc :> VertexCollection)
            this.m_edges <- (ec :> EdgeCollection)
            
    interface ISchemaGraph with
        member this.Vertexes with get() = (box this.m_vertexes) :?> ISchemaVertexCollection
        member this.Edges with get() = (box this.m_edges) :?> ISchemaEdgeCollection